package com.rizzo.analytics.services.web.controller.v1;

import com.rizzo.analytics.services.web.controller.v1.error.ValidationException;
import com.rizzo.analytics.services.web.delegator.AnalyticsDelegatorImpl;
import com.rizzo.infrastructure.web.error.RestError;
import com.rizzo.infrastructure.web.error.RestErrorResolver;
import com.rizzo.infrastructure.web.error.RestExceptionHandler;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.MessageSource;
import org.springframework.http.converter.HttpMessageNotReadableException;
import org.springframework.security.core.context.SecurityContextHolderStrategy;
import org.springframework.util.StringUtils;
import org.springframework.validation.ObjectError;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.context.request.ServletWebRequest;
import org.springframework.web.servlet.LocaleResolver;
import org.springframework.web.servlet.ModelAndView;

import java.util.Arrays;

public class RizzoController {

    protected static final String WILDCARD = "*";
    protected static final String ID_WILDCARD = "-1";
    protected static final String PAGE_SIZE = "10";
    protected static final String ERROR_PAGE_LIMIT_RANGE = "5,10,20,50,75,100";
    protected static final String PERFORMANCE_PAGE_LIMIT_RANGE = "5,10,20,50,75,100";
    protected static final String TREND_PAGE_LIMIT_RANGE = "5,10,20,50,75,100";
    protected static final String APPLICATION_ILLEGAL_CHARS = "*:";

    @Autowired
    protected AnalyticsDelegatorImpl analyticsDelegator;

    @Autowired
    protected SecurityContextHolderStrategy securityContextHolderStrategy;

    @Autowired
    protected RestErrorResolver restErrorResolver;

    @Autowired
    protected RestExceptionHandler restExceptionHandler;

    @Autowired
    private MessageSource messageSource;

    @Autowired
    private LocaleResolver localeResolver;

    protected String getUsernameFromContext() {
        return securityContextHolderStrategy.getContext().getAuthentication().getName();
    }

    @ExceptionHandler({MethodArgumentNotValidException.class})
    protected ModelAndView handleValidationsErrors(ServletWebRequest request, Object handler, MethodArgumentNotValidException e) throws Exception {
        RestError error = restErrorResolver.resolveError(request, handler, e);
        StringBuilder message = new StringBuilder();
        for (ObjectError objectError : e.getBindingResult().getAllErrors()) {
            String messageSourceMessage = messageSource.getMessage(objectError.getDefaultMessage(), objectError.getArguments(), localeResolver.resolveLocale(request.getRequest()));
            message.append("[").append(messageSourceMessage).append("] ");
        }
        error.setMessage(message.toString());
        return restExceptionHandler.getModelAndView(request, handler, error);
    }

    @ExceptionHandler({HttpMessageNotReadableException.class})
    protected ModelAndView handleJsonErrors(ServletWebRequest request, Object handler, HttpMessageNotReadableException e) throws Exception {
        RestError error = restErrorResolver.resolveError(request, handler, e);
        String[] strings = StringUtils.delimitedListToStringArray(e.getMessage(), "\n");
        if (strings.length >= 1) {
            String message = strings[0];
            error.setMessage(message);
        }
        return restExceptionHandler.getModelAndView(request, handler, error);
    }

    protected void validateApplication(String application) throws ValidationException {
        if (StringUtils.hasText(application)) {
            if (org.apache.commons.lang.StringUtils.containsAny(application, APPLICATION_ILLEGAL_CHARS)) {
                throw new ValidationException(40011, "service.save.application.illegal.chars", new Object[]{APPLICATION_ILLEGAL_CHARS});
            }
        }
    }

    protected void validatePaging(long limit, long offset, String limitRange) throws ValidationException {
        String[] allowedLimitValues = StringUtils.delimitedListToStringArray(ERROR_PAGE_LIMIT_RANGE, ",");
        if (!Arrays.asList(allowedLimitValues).contains(String.valueOf(limit))) {
            throw new ValidationException(40012, "service.paging.limit.values.invalid", new Object[]{limitRange});
        }
        if (offset < 0) {
            throw new ValidationException(40012, "service.paging.offset.negative");
        }
    }

    public void setAnalyticsDelegator(AnalyticsDelegatorImpl analyticsDelegator) {
        this.analyticsDelegator = analyticsDelegator;
    }

}
